﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlServerCe;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using WebAnalyser.Api.Interfaces;

namespace WebAnalyser.Library
{
    public class Data
    {
        private readonly SqlCeConnection _connection;
        private string _tableName;
        private string _insertQuery;

        #region Contructor / Destructor
        private Data()
        {
            Debug.WriteLine("Starting Data class engine.");
            string connectionString = string.Format("DataSource=\"{0}\"; Password='{1}'", Settings.ReadValue("Data", "fileName"), Settings.ReadValue("Data", "passWord"));

            if (!File.Exists(Settings.ReadValue("Data", "fileName")))
            {
                try
                {
                    SqlCeEngine engine = new SqlCeEngine(connectionString);
                    engine.CreateDatabase();
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message, e.GetType().ToString());
                }
            }
            try
            {
                _connection = new SqlCeConnection(connectionString);
                _connection.Open();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, e.GetType().ToString());
            }
        }

        ~Data()
        {
            Debug.WriteLine("Disposing Data class engine.");
            _connection.Close();
        }
        #endregion Contructor / Destructor

        #region Singleton
        private static readonly Object SyncLock = new Object();

        private static volatile Data _instance;
        /// <summary>
        /// Gets the instance.
        /// </summary>
        /// <value>The instance.</value>
        public static Data Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (SyncLock)
                    {
                        if (_instance == null)
                        {
                            _instance = new Data();
                        }
                    }
                }
                return _instance;
            }
        }
        #endregion Singleton

        #region Sql strings builders
        /// <summary>
        /// Gets the create table query.
        /// </summary>
        /// <returns></returns>
        private string GetCreateTableQuery()
        {
            string query = "CREATE TABLE " + _tableName + "("
                           + "uri ntext NOT NULL,"
                           + "error " + SqlDbType.NText;
            foreach (KeyValuePair<string, IPluginDefinition> pluginDefinition in Plugins.Instance.PluginsDefinitions)
            {
                query += string.Format(",{0} {1}", pluginDefinition.Value.DbColumnName, pluginDefinition.Value.DbColumnType);
            }
            query += ')';
            return query;
        }

        /// <summary>
        /// Gets the insert query.
        /// </summary>
        /// <returns></returns>
        private string GetInsertQuery()
        {
            string query = "INSERT INTO " + _tableName + " (uri,error";
            foreach (KeyValuePair<string, IPluginDefinition> pluginDefinition in Plugins.Instance.PluginsDefinitions)
            {
                query += ',' + pluginDefinition.Value.DbColumnName;
            }
            query += ") VALUES (?,?";
            query = Plugins.Instance.PluginsDefinitions.Aggregate(query, (current, t) => current + ",?");
            query += ')';
            return query;
        }
        #endregion Sql strings builders

        /// <summary>
        /// Creates the table.
        /// </summary>
        /// <param name="tableName">Name of the table.</param>
        public void CreateTable(string tableName)
        {
            _tableName = tableName + "_";
            if (DateTime.Now.Month < 10)
                _tableName += "0";
            _tableName += DateTime.Now.Month + "_";
            if (DateTime.Now.Day < 10)
                _tableName += "0";
            _tableName += DateTime.Now.Day + "_" + DateTime.Now.Year + "_";
            if (DateTime.Now.Hour < 10)
                _tableName += "0";
            _tableName += DateTime.Now.Hour + "_";
            if (DateTime.Now.Minute < 10)
                _tableName += "0";
            _tableName += DateTime.Now.Minute + "_";
            if (DateTime.Now.Second < 10)
                _tableName += "0";
            _tableName += DateTime.Now.Second.ToString();

            try
            {
                SqlCeCommand cmd = _connection.CreateCommand();
                cmd.CommandText = GetCreateTableQuery();
                cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, e.GetType().ToString());
            }
        }

        /// <summary>
        /// Inserts the data.
        /// </summary>
        /// <param name="args">The args.</param>
        public void InsertData(params object[] args)
        {
            if (String.IsNullOrEmpty(_insertQuery))
            {
                _insertQuery = GetInsertQuery();
            }

            SqlCeCommand cmd = new SqlCeCommand(_insertQuery, _connection);
            cmd.Parameters.Add(new SqlCeParameter("uri", SqlDbType.NText));
            cmd.Parameters.Add(new SqlCeParameter("error", SqlDbType.NText));
            cmd.Parameters.Add(new SqlCeParameter("css", SqlDbType.NText));
            cmd.Parameters.Add(new SqlCeParameter("js", SqlDbType.NText));
            cmd.Parameters["uri"].Value = args[0];
            cmd.Parameters["error"].Value = args[1];
            cmd.Parameters["css"].Value = "";
            cmd.Parameters["js"].Value = "";
            cmd.ExecuteNonQuery(); 
        }
    }
}